package com.knirirr.beecountclassic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.PowerManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.text.InputType;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import java.io.File;
import org.apache.commons.lang3.StringUtils;

public class CountingActivity extends Activity implements OnClickListener
{
  TextView titleCounting;
  String projName;
  long projId;
  DbHelper dbHelper;
  Cursor cursor;
  SQLiteDatabase db;
  LinearLayout layout;
  HashMap<String,String> currcount;
  HashMap<String,Integer> auto_resets;
  HashMap<String,Integer> reset_levels;
  //HashMap<String, Map<Integer, String>> alerts;
  HashMap<String, List<Map<Integer,String>>> alerts;
  AlertDialog alert;
  static final String TAG = "BeeCountCountingActivity";
  Typeface font;
  private PowerManager.WakeLock wl;
  int longPressId;
  HashMap<Integer,String> resets;
  HashMap<String,Link> links;
  String divider;
  int linked;
  int countWidth;
  ActionBar actionBar;
  Intent intent;
  int showingHelp;
  SharedPreferences prefs;
  Boolean fontPref;
  Boolean swapPref;
  Boolean awakePref;
  Boolean toastPref;
  Boolean showextras;
  String notes;
  Integer spinMax;


  /** Called when the activity is first created. */
  @Override
  @SuppressWarnings("deprecation")
  @SuppressLint("UseSparseArrays")
  public void onCreate(Bundle savedInstanceState) 
  {
    if (android.os.Build.VERSION.SDK_INT < 11)
    {
      setTheme(android.R.style.Theme_NoTitleBar);
    }
    super.onCreate(savedInstanceState);
    setContentView(R.layout.counting);
    longPressId = 0; // to keep track of resets
    resets = new HashMap<Integer,String>();
    linked = 0;
    showingHelp = 0;
    showextras = false;

    // layout in which to put the new things which appear
    layout = (LinearLayout) findViewById(R.id.countCountLayout);

    // background
    prefs = PreferenceManager.getDefaultSharedPreferences(this);
    String backgroundPref = prefs.getString("pref_back", "default");
    fontPref = prefs.getBoolean("pref_font", true);
    swapPref = prefs.getBoolean("pref_swap", false);
    awakePref = prefs.getBoolean("pref_awake", true);
    String pictPref = prefs.getString("imagePath", "");
    spinMax = Integer.parseInt(prefs.getString("spinmax","500"));
    toastPref = prefs.getBoolean("toast_away", false);

    LinearLayout layout = (LinearLayout) findViewById(R.id.countingScreen);
    if (backgroundPref.equals("none"))
    {
       // boring black screen
    }
    else if (backgroundPref.equals("custom"))
    {
      if (!(pictPref.equals(""))) 
      {
        if (new File(pictPref).isFile())
        {
          layout.setBackgroundDrawable(BackgroundImage.decodeSampledBitmapFromResource(pictPref,CountingActivity.this));
        }
        else
        {
          Toast.makeText(this,getString(R.string.customMissing),Toast.LENGTH_SHORT).show();
          layout.setBackgroundResource(R.drawable.beecount_knitting);
        }
      }
      else
      {
        Toast.makeText(this,getString(R.string.customNotDefined),Toast.LENGTH_SHORT).show();
        layout.setBackgroundResource(R.drawable.beecount_knitting);
      }
    }
    else if (backgroundPref.equals("default"))
    {
      layout.setBackgroundResource(R.drawable.beecount_knitting);
    } 

    // awesome font
    if (fontPref == true)
    {
      font = Typeface.createFromAsset(getAssets(), "village.ttf");
    }
    

    // keep track of counts before saving
    currcount = new HashMap<String,String>();

    // which counts will reset themselves at a pre-defined count
    auto_resets = new HashMap<String,Integer>();

    // to what should each count be reset?
    reset_levels = new HashMap<String,Integer>();

    // which counts will have pop-up alerts
    //alerts = new HashMap<String, Map<Integer, String>>();
    alerts = new HashMap<String, List<Map<Integer,String>>>();
    
    // what links to what
    links = new HashMap<String,Link>();

    Button saveButton = (Button) findViewById(R.id.saveCountsButton);
    saveButton.setOnClickListener(this);
    saveButton.setTag("saveButton");
    if (fontPref == true)
    {
      saveButton.setTypeface(font);
    }

    //Read more: http://getablogger.blogspot.com/2008/01/android-pass-data-to-activity.html#ixzz1lhGnzZpZ
    Bundle extras = getIntent().getExtras(); 
    if(extras !=null)
    {
      projName = extras.getString("projName");
      projId = extras.getLong("projId");
    }

    // set up title &c.
    titleCounting = (TextView) findViewById(R.id.titleCounting);
    titleCounting.setText(projName.replaceAll("(^')|('$)","").replaceAll("''","'"));
    if (fontPref == true)
    {
      titleCounting.setTypeface(font);
    }

    // screen size must be found to get button width
    int width = getWindowManager().getDefaultDisplay().getWidth();
    if (width >= 400)
    {
      countWidth = 100;
    }
    else
    {
      countWidth = 50;
    }

    // get database
    dbHelper = new DbHelper(this);
    db = dbHelper.getReadableDatabase();

    Log.i(TAG,"Starting up!");

    // the screen should not dim during counting
    // http://www.tutorials-android.com//code_examples/How_to_stop_screen_from_dimming_by_enforcing_wake_lock.rhtml
    if (awakePref == true)
    {
      PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
      wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "DoNotDimScreen");
    }

  }

  /*
   * the reason for drawing the screen using this method, called during onResume, is
   * that users may pop back and forth between screens whilst editing, and the screen must
   * be redrawn to reflect their latest edits.
   */
  @SuppressWarnings("deprecation")
  @SuppressLint("UseSparseArrays")
  private void drawScreen()
  {
    // clear the layout
    layout.removeAllViewsInLayout();

    // query database for the data
    try
    {
      cursor = db.query(DbHelper.COUNT_TABLE, new String[] {DbHelper.C_ID, DbHelper.C_NAME, DbHelper.C_COUNT, DbHelper.C_AUTO_RESET, DbHelper.C_RESET_LEVEL}, DbHelper.C_PROJECT_ID + "=?", new String[] { String.valueOf(projId) }, null, null, null); // stuff
    }
    catch (Exception e)
    {
      AlertDialog.Builder alert = new AlertDialog.Builder(this);

      alert.setTitle(getString(R.string.codeCockup));
      alert.setMessage(getString(R.string.excuses));

      alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          // Canceled.
        }
      });
      alert.show();
    }
    startManagingCursor(cursor);


    // get the data, display and that
    String name;
    long value;
    int a_reset;
    //int a_lert;
    int a_level;
    int count_id;
    //String a_lert_txt;

    while (cursor.moveToNext())
    {
      count_id = cursor.getInt(cursor.getColumnIndex(DbHelper.C_ID));
      name = cursor.getString(cursor.getColumnIndex(DbHelper.C_NAME));      
      value = cursor.getLong(cursor.getColumnIndex(DbHelper.C_COUNT));      
      a_reset = cursor.getInt(cursor.getColumnIndex(DbHelper.C_AUTO_RESET));      
      a_level = cursor.getInt(cursor.getColumnIndex(DbHelper.C_RESET_LEVEL));      
      //a_lert = cursor.getInt(cursor.getColumnIndex(DbHelper.C_ALERT));
      //a_lert_txt = cursor.getString(cursor.getColumnIndex(DbHelper.C_ALERT_TEXT));

      //if (a_reset > 0 || a_lert > 0)
      if (a_reset > 0)
      {
        showextras = true;
      }

      // some hashes to track auto resets and alerts
      auto_resets.put(name,a_reset);
      reset_levels.put(name,a_level);
      create_alerts(count_id,name);
      //HashMap<Integer,String> newalert = new HashMap<Integer,String>();
      //newalert.put(a_lert,a_lert_txt);
      //alerts.put(name,newalert);
      //Log.i(TAG,"Name: " + name + ", Value: " + value);

      // now create some new objects and layouts
      LinearLayout row = new LinearLayout(this);
      //row.setOrientation(0);
      row.setOrientation(LinearLayout.HORIZONTAL);
      row.setBackgroundColor(getResources().getColor(R.color.clear));

      TextView title = new TextView(this);
      title.setText(name);
      title.setTextSize(TypedValue.COMPLEX_UNIT_DIP,25);
      if (fontPref == true)
      {
        title.setTypeface(font);
      }
      title.setGravity(Gravity.LEFT);
      title.setTextColor(Color.WHITE);
      title.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,1));
      title.setHorizontallyScrolling(false);
      title.setMaxLines(100);
      registerForContextMenu(title); // reset to 0

      TextView counting = new TextView(this);
      counting.setText(String.valueOf(value));
      counting.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,0));
      counting.setTag(name + "_count");
      counting.setGravity(Gravity.RIGHT);
      counting.setTextSize(TypedValue.COMPLEX_UNIT_DIP,25);
      if (fontPref == true)
      {
        counting.setTypeface(font);
      }
      counting.setTextColor(Color.WHITE);
      //resets.add(name + "_count");

      Button countUp = new Button(this);
      countUp.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,0));
      countUp.setText(R.string.buttonCountUp);
      countUp.setOnClickListener(this);
      countUp.setTag(name + "_up");
      countUp.setTextSize(TypedValue.COMPLEX_UNIT_DIP,25);
      countUp.setWidth(countWidth);

      Button countDown = new Button(this);
      countDown.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,0));
      countDown.setText(R.string.buttonCountDown);
      countDown.setOnClickListener(this);
      countDown.setTag(name + "_down");
      countDown.setTextSize(TypedValue.COMPLEX_UNIT_DIP,25);
      countDown.setWidth(countWidth);

      if (swapPref == true)
      {
        row.addView(countDown);
        row.addView(title);
        row.addView(counting);
        row.addView(countUp);
      }
      else
      {
        row.addView(countUp);
        row.addView(title);
        row.addView(counting);
        row.addView(countDown);
      }

      layout.addView(row,new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    }

    // show any links which may exist
    String master;
    String slave;
    long increment;
    long type;
    try 
    {
      cursor = db.query(DbHelper.LINK_TABLE, new String[] {DbHelper.L_MASTER, DbHelper.L_SLAVE,DbHelper.L_INCREMENT,DbHelper.L_TYPE}, DbHelper.L_PROJECT_ID + "=?", new String[] { String.valueOf(projId) }, null, null, null); // stuff
    }
    catch (Exception e)
    {
      AlertDialog.Builder alert = new AlertDialog.Builder(this);

      alert.setTitle(getString(R.string.codeCockup));
      alert.setMessage(getString(R.string.excuses));

      alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          // Canceled.
        }
      });
      alert.show();
    }
    startManagingCursor(cursor);
    while (cursor.moveToNext())
    {
      master = cursor.getString(cursor.getColumnIndex(DbHelper.L_MASTER));      
      slave = cursor.getString(cursor.getColumnIndex(DbHelper.L_SLAVE));      
      increment = cursor.getLong(cursor.getColumnIndex(DbHelper.L_INCREMENT));      
      type = cursor.getLong(cursor.getColumnIndex(DbHelper.L_TYPE));      

      LinearLayout currLink = new LinearLayout(this);
      //currLink.setOrientation(0);
      currLink.setOrientation(LinearLayout.HORIZONTAL);
      currLink.setTag("old_" + master + "#" + slave + "_link");
      currLink.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL);

      TextView summary = new TextView(this);
      String incr; 
      if (type == 0)
      {
        incr = getString(R.string.incr_reset);
      }
      else
      {
        incr = getString(R.string.incr);
      }
      String ev = getString(R.string.ev);
      if (android.os.Build.VERSION.SDK_INT < 11)
      {
        summary.setText(EditprojActivity.truncate(master,7) + " " + incr + " " + EditprojActivity.truncate(slave,7) + " "  + ev + " " + String.valueOf(increment) + "."); // long values push the button off screen
      }
      else
      {
        summary.setText(master + " " + incr + " " + slave + " "  + ev + " " + String.valueOf(increment) + "."); // might work for ICS+
      }
      summary.setTextSize(TypedValue.COMPLEX_UNIT_DIP,12);
      if (fontPref == true)
      {
        summary.setTypeface(font);
      }
      summary.setTextColor(Color.WHITE);
      summary.setGravity(Gravity.CENTER);
      summary.setHorizontallyScrolling(true);

      currLink.addView(summary);
      layout.addView(currLink,new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
    }

    // do the same for auto resets and alerts
    // doing this twice is very naughty indeed, and I should revisit this to fix the problem
    if (showextras == true)
    {
      cursor = db.query(DbHelper.COUNT_TABLE, new String[] {DbHelper.C_NAME, DbHelper.C_COUNT, DbHelper.C_AUTO_RESET}, DbHelper.C_PROJECT_ID + "=?", new String[] { String.valueOf(projId) }, null, null, null); // stuff
      startManagingCursor(cursor);

      while (cursor.moveToNext())
      {
        name = cursor.getString(cursor.getColumnIndex(DbHelper.C_NAME));      
        value = cursor.getLong(cursor.getColumnIndex(DbHelper.C_COUNT));      
        a_reset = cursor.getInt(cursor.getColumnIndex(DbHelper.C_AUTO_RESET));      
        //a_lert = cursor.getInt(cursor.getColumnIndex(DbHelper.C_ALERT));
        //a_lert_txt = cursor.getString(cursor.getColumnIndex(DbHelper.C_ALERT_TEXT));


        if (a_reset > 0)
        {
          LinearLayout currLink = new LinearLayout(this);
          //currLink.setOrientation(0);
          currLink.setOrientation(LinearLayout.HORIZONTAL);
          currLink.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL);
          TextView reset = new TextView(this);
          reset.setText(name + " " + getString(R.string.willReset) + " " + String.valueOf(a_reset) + "."); // might work for ICS+
          reset.setTextSize(TypedValue.COMPLEX_UNIT_DIP,12);
          if (fontPref == true)
          {
            reset.setTypeface(font);
          }
          reset.setTextColor(Color.WHITE);
          reset.setGravity(Gravity.CENTER);
          reset.setHorizontallyScrolling(true);
          currLink.addView(reset);
          layout.addView(currLink,new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
        }
        /*
        if (a_lert > 0)
        {
          LinearLayout currLink = new LinearLayout(this);
          currLink.setOrientation(0);
          currLink.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL);
          TextView alert = new TextView(this);
          alert.setText(name + " " + getString(R.string.willAlert) + " " + String.valueOf(a_lert) + "."); // might work for ICS+
          alert.setTextSize(TypedValue.COMPLEX_UNIT_DIP,12);
          if (fontPref == true)
          {
            alert.setTypeface(font);
          }
          alert.setTextColor(Color.WHITE);
          alert.setGravity(Gravity.CENTER);
          alert.setHorizontallyScrolling(true);
          currLink.addView(alert);
          layout.addView(currLink,new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
        }
        */
      }
    }

    // now the notes ought to be shown, below everything else
    try 
    {
      cursor = db.query(DbHelper.PROJ_TABLE, new String[] {DbHelper.P_NOTES,DbHelper.P_NAME}, DbHelper.P_ID + "=?", new String[] { String.valueOf(projId) }, null, null, null); // stuff
    }
    catch (Exception e)
    {
      AlertDialog.Builder alert = new AlertDialog.Builder(this);

      alert.setTitle(getString(R.string.codeCockup));
      alert.setMessage(getString(R.string.excuses));

      alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          // Canceled.
        }
      });
      alert.show();
    }
    startManagingCursor(cursor);

    while (cursor.moveToNext())
    {
      notes = cursor.getString(cursor.getColumnIndex(DbHelper.P_NOTES));
      projName = cursor.getString(cursor.getColumnIndex(DbHelper.P_NAME));
    }

    if (!StringUtils.isBlank(notes))
    {
      TextView note_view = new TextView(this);
      note_view.setText(notes); 
      if (fontPref == true)
      {
        note_view.setTypeface(font);
      }
      note_view.setTextColor(Color.WHITE);
      note_view.setPadding(10,10,10,10);
      layout.addView(note_view,new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
    }
    if (!StringUtils.isBlank(projName))
    {
      TextView title = (TextView) findViewById(R.id.titleCounting);
      title.setText(projName);
    }
  }

  /*
    Search all the alerts and load them up into the horrid data structure which tracks them
    whilst the count activity is running
   */
  private void create_alerts(int count_id, String name)
  {
    Cursor alert_cursor;
    //Log.i(TAG, "Creating alerts for: " + String.valueOf(count_id) + ", " + name);
    try
    {
      alert_cursor = db.query(DbHelper.ALERT_TABLE, new String[] {DbHelper.A_ID, DbHelper.A_COUNT_ID, DbHelper.A_ALERT, DbHelper.A_ALERT_TEXT}, DbHelper.A_COUNT_ID + "=?", new String[] { String.valueOf(count_id) }, null, null, null); // stuff
    }
    catch (Exception e)
    {
      AlertDialog.Builder alert = new AlertDialog.Builder(this);

      alert.setTitle(getString(R.string.codeCockup));
      alert.setMessage(getString(R.string.excuses));

      alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          // Canceled.
        }
      });
      alert.show();
      return;
    }
    startManagingCursor(alert_cursor);
    Boolean gotsome = false;
    while (alert_cursor.moveToNext())
    {
      String a_lert_txt =  alert_cursor.getString(alert_cursor.getColumnIndex(DbHelper.A_ALERT_TEXT));
      int a_lert =  alert_cursor.getInt(alert_cursor.getColumnIndex(DbHelper.A_ALERT));
      HashMap<Integer,String> newalert = new HashMap<Integer,String>();
      newalert.put(a_lert,a_lert_txt);
      if (alerts.containsKey(name))
      {
        alerts.get(name).add(newalert);
      }
      else
      {
        List list = new ArrayList<Map<Integer,String>>();
        list.add(newalert);
        alerts.put(name, list);
      }
      showextras = true; // if any alerts are found
      //Log.i(TAG, "Got values: " + a_lert_txt + ", " + String.valueOf(a_lert));
      gotsome = true;
    }
    if (gotsome == false)
    {
      HashMap<Integer,String> newalert = new HashMap<Integer,String>();
      List list = new ArrayList<Map<Integer,String>>();
      alerts.put(name,list);
    }

    stopManagingCursor(alert_cursor);
    alert_cursor.close();
  }

  @SuppressWarnings("deprecation")
  private void getLink()
  {
    // clear links here, otherwise a hashmap could still be hanging around after the user has deleted
    // it, resulting in apparently deleted counts still functioning!
    links.clear();

    // query database for the data
    try
    {
      cursor = db.query(DbHelper.LINK_TABLE, new String[] {DbHelper.L_MASTER, DbHelper.L_SLAVE, DbHelper.L_INCREMENT, DbHelper.L_TYPE}, DbHelper.L_PROJECT_ID + "=?", new String[] { String.valueOf(projId) }, null, null, null); // stuff
    }
    catch (Exception e)
    {
      AlertDialog.Builder alert = new AlertDialog.Builder(this);

      alert.setTitle(getString(R.string.codeCockup));
      alert.setMessage(getString(R.string.excuses));

      alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          // Canceled.
        }
      });
      alert.show();
    }

    startManagingCursor(cursor);

    if (cursor.getCount() == 0)
    {
      //Log.i(TAG,"No linked counts for this project");
      return;
    }
    else
    {
      linked = 1;
    }

    // get the data, display and that
    Link l;
    String oldmaster = "";
    while (cursor.moveToNext())
    {
      String master = cursor.getString(cursor.getColumnIndex(DbHelper.L_MASTER));      
      String slave = cursor.getString(cursor.getColumnIndex(DbHelper.L_SLAVE));      
      long increment = cursor.getLong(cursor.getColumnIndex(DbHelper.L_INCREMENT));      
      long type = cursor.getLong(cursor.getColumnIndex(DbHelper.L_TYPE));      
      if (master.equals(oldmaster))
      {
        links.get(master).addSlave(slave,(int)increment,(int)type); 
      }
      else
      {
        l = new Link();
        l.addSlave(slave,(int)increment,(int)type);
        links.put(master,l);
      }
      oldmaster = master;
    }
    //Log.i("LINKS: ", links.toString());
  }

  @Override
  protected void onDestroy()
  {
    super.onDestroy();
    db.close();
  }

  @Override
  protected void onResume()
  {
    super.onResume();
    showingHelp = 0;
    if (awakePref == true)
    {
      wl.acquire(); // acquire wake lock
    }
    drawScreen();
    getLink();

  }

  @Override
  protected void onPause()
  {
    super.onPause();
    // save the data
    if (showingHelp == 0)
    {
      boolean saved_correctly = saveData();
      if (saved_correctly)
      {
        Toast.makeText(CountingActivity.this, getString(R.string.projSaving) + " " + projName + "!",Toast.LENGTH_SHORT).show();
      }
      else
      {
        Toast.makeText(CountingActivity.this,R.string.bizarreError,Toast.LENGTH_SHORT).show();
      }
    }
    // release the wake lock
    if (awakePref == true)
    {
      if (wl.isHeld())
      {
        try
        {
          wl.release();
        }
        catch (Exception e)
        {
          Log.e(TAG, "Couldn't release wakelock: " + e.toString());
        }
      }
    }
  }

  // a menu for editing and deleting projects
  @Override
  @TargetApi(14)
  public boolean onCreateOptionsMenu(Menu menu)
  {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    if (android.os.Build.VERSION.SDK_INT > 13)
    {
      actionBar = getActionBar();                                                                                         
      actionBar.setHomeButtonEnabled(true);                                                                               
    }
    return true;
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item)
  {
    switch (item.getItemId())
    {
      case R.id.editProj:
        intent = new Intent(this,EditprojActivity.class);
        intent.putExtra("projId",projId);
        intent.putExtra("projName",projName);
        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        startActivity(intent);
        break;
      case R.id.mainHelp:
        showingHelp = 1;
        intent = new Intent(this,MainHelpActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        startActivity(intent);
        break;
      case R.id.deleteProj:
        deleteProj();
        break;
      case android.R.id.home:
        startActivity(new Intent(this, WelcomeActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
        break;
      default:
        return super.onOptionsItemSelected(item);
    }
    return true;
  }


  // delete the project on confirmation
  private void deleteProj()
  {
    // http://developer.android.com/guide/topics/ui/dialogs.html#AlertDialog
    // could make the dialog central in the popup - to do later
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setIcon(android.R.drawable.ic_dialog_alert);
    builder.setMessage(R.string.confirmDelete).setCancelable(false).setPositiveButton(R.string.yesButton, new DialogInterface.OnClickListener()
    {
      public void onClick(DialogInterface dialog, int id) 
      {
        //Log.i(TAG,"Would have deleted!");
        // http://stackoverflow.com/questions/4095309/sqlite-delete-query-syntax-in-android
        db.execSQL("delete from " + DbHelper.LINK_TABLE + " where project_id = " + projId);
        db.execSQL("delete from " + DbHelper.COUNT_TABLE + " where project_id = " + projId);
        db.execSQL("delete from " + DbHelper.PROJ_TABLE + " where _id = " + projId);
        startActivity(new Intent(getApplicationContext(), ListprojActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
      }
    }).setNegativeButton(R.string.noButton, new DialogInterface.OnClickListener() 
    {
      public void onClick(DialogInterface dialog, int id) 
      {
        dialog.cancel();
      }
     });
    alert = builder.create();
    alert.show();
  }

  // save on save button click or on pause
  private boolean saveData()
  {
    // get the values of all the views and shove them into
    // the database, then:
    for (Map.Entry<String, String> entry : currcount.entrySet()) 
    { 
      ContentValues dataToInsert = new ContentValues();                          
      dataToInsert.put(DbHelper.C_COUNT, entry.getValue().replaceAll("_","-"));
      String where = "project_id=? and name=?";
      String[] whereArgs = {String.valueOf(projId),entry.getKey()};
      db.update(DbHelper.COUNT_TABLE, dataToInsert, where, whereArgs);
    }
    // repeat the above for auto resets
    for (Map.Entry<String, Integer> entry : auto_resets.entrySet()) 
    { 
      ContentValues dataToInsert = new ContentValues();                          
      dataToInsert.put(DbHelper.C_AUTO_RESET, entry.getValue());
      String where = "project_id=? and name=?";
      String[] whereArgs = {String.valueOf(projId),entry.getKey()};
      db.update(DbHelper.COUNT_TABLE, dataToInsert, where, whereArgs);
    }
    // repeat the above for  alerts
    //HashMap<String, List<Map<Integer,String>>> alerts;
    //for (List<Map<Integer,String>> e : entry)
    /*
    for (Map.Entry<String, List<Map<Integer,String>>> entry : alerts.entrySet())
    {
      String tcount = entry.getKey();
      List<Map<Integer, String>> tvals = entry.getValue();
      for (List<Map<Integer, String>> e : entry)
      {
        ContentValues dataToInsert = new ContentValues();
        for (Map.Entry<Integer, String> subentry : e.entrySet())
        {
          dataToInsert.put(DbHelper.A_ALERT, subentry.getKey());
          dataToInsert.put(DbHelper.A_ALERT_TEXT, subentry.getValue());
        }
        String where = "count_id=?";
        String[] whereArgs = {String.valueOf(count_id)};
        db.update(DbHelper.ALERT_TABLE, dataToInsert, where, whereArgs);
      }
    }
    */
    // ...not forgetting reset levels
    for (Map.Entry<String, Integer> entry : reset_levels.entrySet()) 
    { 
      ContentValues dataToInsert = new ContentValues();                          
      dataToInsert.put(DbHelper.C_RESET_LEVEL, entry.getValue());
      String where = "project_id=? and name=?";
      String[] whereArgs = {String.valueOf(projId),entry.getKey()};
      db.update(DbHelper.COUNT_TABLE, dataToInsert, where, whereArgs);
    }

    return true;
  }

  public void onClick(View view)
  {
    String viewTag = (String) view.getTag();
    if (viewTag.equals("saveButton"))
    {
      Toast.makeText(CountingActivity.this, getString(R.string.projSaving) + " " + projName + "!",Toast.LENGTH_SHORT).show();
      saveData();
      finish();
    }
    else
    {
      String[] clicked = viewTag.split("_");
      TextView curr_count = (TextView) layout.findViewWithTag(clicked[0] + "_count");
      int value =  Integer.parseInt(curr_count.getText().toString());
      // there's some poor quality code here where exceptions are caught in case
      // someone has put something other than an int into the counting box. This
      // ought to be improved at some point
      boolean up = true;
      if (clicked[1].equals("up"))
      {
        try 
        {
          value = value + 1;
        }
        catch (Exception e) { return; }
      }
      else
      {
        up = false;
        try 
        {
          value = value - 1;
        }
        catch (Exception e) { return; }
      }
      if (value < 0) { value = 0; }
      // if two counts are linked
      if (linked == 1)
      {
        incLink(clicked[0], value, up);
      }
      // see if an auto-reset is required
      int ar = auto_resets.get(clicked[0]);
      int rt = reset_levels.get(clicked[0]);
      if (ar > rt && value >= ar)
      {
        value = rt;
        Toast.makeText(CountingActivity.this, clicked[0] + " " + getString(R.string.hasAutoReset),Toast.LENGTH_SHORT).show();
      }
      // see if a row count alert is required
      List<Map<Integer,String>> tvals = alerts.get(clicked[0]);
      doAlert(tvals, value);

      // set the current value
      curr_count.setText(String.valueOf(value));
      // update the global hash with count values, ready for saving
      currcount.put(clicked[0],String.valueOf(value));

    }
  }

  /*
   * alerts have been moved here so they can be checked
   * for in linked counts as well as standard counts (oops)
   */
  private void doAlert(List<Map<Integer,String>> tvals, Integer value)
  {
    for (Map<Integer,String> uvals : tvals)
    {
      for (Map.Entry<Integer, String> subentry : uvals.entrySet())
      {
        if (subentry.getKey() > 0 && value == subentry.getKey())
        {
          AlertDialog.Builder alert = new AlertDialog.Builder(this);

          alert.setTitle(getString(R.string.alertTitle));
          alert.setMessage(subentry.getValue());

          alert.setNegativeButton("OK", new DialogInterface.OnClickListener()
          {
            public void onClick(DialogInterface dialog, int whichButton)
            {
              // Canceled.
            }
          });
          alert.show();
        }
      }
    }
  }

  /*
   * I don't link all the joins that I've done here, but at least it works.
   * I'm relying on substituting all "_" characters from users' input.
   * This is crap and the code ought to be re-factored at some point.
   */
  private void incLink(String link, int value, boolean up)
  {
    if (links.containsKey(link))
    {
      // Log.i("LOOPING: ","------");
      for (Map.Entry<String, int[]> entry : links.get(link).getSlaves().entrySet())
      {
        String slave = (String) entry.getKey();
        Integer increment = (int) entry.getValue()[0];
        Integer type = (int) entry.getValue()[1];
        TextView s_count = (TextView) layout.findViewWithTag(slave + "_count");
        int s_value = 0;
        try
        {
          s_value =  Integer.parseInt(s_count.getText().toString());
        }
        catch (Exception e)
        {
          Log.e(TAG,"Failed to get count from " + slave + "_count");
          Toast.makeText(CountingActivity.this, getString(R.string.linkError) + " " + slave,Toast.LENGTH_LONG).show();
          return;
        }
        /*
        Log.i("MASTER: ", link + "," + String.valueOf(value));
        Log.i("SLAVE: ", slave);
        Log.i("UP: ", String.valueOf(up));
        Log.i("LINKS: ", links.get(link).getSlaves().entrySet().toString());
        */
        if (up == true)
        {
          int hasBeenReset = 0;
          if ((value > 0) && (value % increment == 0))
          {
            /*
             * add code here which will check the type of the link; inc(rement) or res(et). In the case of the 
             * former, carry on as usual. For the latter, reset the slave to 0. 
             * To store link types, set up a hash on activity start with master_slave => type.
             */
            if (type == 0)
            {
              //try
              //{
                int rt = reset_levels.get(slave);
                s_value = rt;
              //}
              //catch (Exception e) { return; }
              s_count.setText(String.valueOf(s_value));
              currcount.put(slave,String.valueOf(s_value));
              if (toastPref == false)
              {
                Toast.makeText(CountingActivity.this, link + " " + getString(R.string.postReset) + " " + slave + "!",Toast.LENGTH_SHORT).show();
              }
            }
            else if (type == 1) // check here for an increment message
            {
              try
              {
                s_value++;
                int ar = auto_resets.get(slave);
                if (ar > 0 && s_value >= ar)
                {
                  hasBeenReset = s_value;
                  s_value = 0;
                  Toast.makeText(CountingActivity.this, slave + " " + getString(R.string.hasAutoReset),Toast.LENGTH_SHORT).show();
                }
                List<Map<Integer,String>> tvals = alerts.get(slave);
                doAlert(tvals, s_value);
              }
              catch (Exception e) { return; }
              s_count.setText(String.valueOf(s_value));
              currcount.put(slave,String.valueOf(s_value));
              try
              {
                if (toastPref == false)
                {
                  Toast.makeText(CountingActivity.this, link + " " + getString(R.string.postIncr) + " " + slave + "!",Toast.LENGTH_SHORT).show();
                }
              }
              catch (Exception e)
              {
                Log.e(TAG,"Strange toast exception: " + e.toString());
              }
            }
            else
            {
              Toast.makeText(CountingActivity.this, getString(R.string.randomFail),Toast.LENGTH_SHORT).show();
            }
            /* 
             * at this point, if the slave is itself a master, then a second count will be incremented
             */
            if (hasBeenReset > 0)
            {
              incLink(slave,hasBeenReset,up);
            }
            else
            {
              incLink(slave,s_value,up);
            }
          }
        }
        else
        {
          if ((value > 0) && ((value + 1) % increment == 0))
          {
            if (type == 1)
            {
              try
              {
                s_value--;
              }
              catch (Exception e) { return; }
              if (s_value >= 0)
              {
                s_count.setText(String.valueOf(s_value));
                currcount.put(slave,String.valueOf(s_value));
                if (toastPref == false)
                {
                  Toast.makeText(CountingActivity.this, link + " " + getString(R.string.postDecr) + " " + slave + "!",Toast.LENGTH_SHORT).show();
                }
              }
              /* 
               * at this point, if the slave is itself a master, then a second count will be incremented
               */
              incLink(slave,s_value,up);
            }
          }
        }
      }
    }
    else
    {
      //Log.i("LINKS: ", "...doesn't contain " + link);
    }
  }

  class Link 
  {
    private HashMap<String,int[]> slaves = new HashMap<String, int[]>();

    public void addSlave(String s, Integer i,Integer j)
    {
      int[] arr = new int[]{i,j};
      this.slaves.put(s,arr);
    }

    public Map<String,int[]> getSlaves() 
    {
      return slaves;
    }

  }

  

  // context menu for reset to zero
  // this looks horrible to me - suggestions welcome!
  // what I'm trying to do is create a hash of ids => count names so that when a context menu is created on the fly
  // the one can be associated to the others
  @Override
  public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) 
  {
    super.onCreateContextMenu(menu, v, menuInfo);
    TextView t = (TextView) v;

    // this section deals with the menu entry to reset a count to 0
    String title = t.getText() + ": " + getString(R.string.resetCount) + " " + reset_levels.get(t.getText());
    if (resets.containsValue(t.getText() + "_count" + "_reset"))
    {
      int pressid;
      for (Map.Entry<Integer, String> entry : resets.entrySet()) 
      {
        pressid = entry.getKey();
        String value = entry.getValue();
        //Log.i("KEY, VAL: ", Integer.toString(pressid) + " : " + value);
        if (value.equals(t.getText() + "_count" + "_reset"))
        {
          //Log.i("IN THE LOOP: ", Integer.toString(pressid));
          menu.add(0, pressid, 0, title);        
          break;
        }
      }
    }
    else
    {
      menu.add(0, longPressId, 0, title);        
      resets.put(longPressId,(String) t.getText() + "_count" + "_reset");
      longPressId++;
    }

    // this is to open the reset-level activity
    String level =  t.getText() + ": " + getString(R.string.srl);
    if (resets.containsValue(t.getText() + "_count" + "_level"))
    {
      int pressid;
      for (Map.Entry<Integer, String> entry : resets.entrySet()) 
      {
        pressid = entry.getKey();
        String value = entry.getValue();
        //Log.i("KEY, VAL: ", Integer.toString(pressid) + " : " + value);
        if (value.equals(t.getText() + "_count" + "_level"))
        {
          //Log.i("IN THE LOOP: ", Integer.toString(pressid));
          menu.add(0, pressid, 0, level);        
          break;
        }
      }
    }
    else
    {
      menu.add(0, longPressId, 0, level);        
      resets.put(longPressId,(String) t.getText() + "_count" + "_level");
      longPressId++;
    }


    // this is to open the auto-reset activity
    String auto =  t.getText() + ": " + getString(R.string.sar);
    if (resets.containsValue(t.getText() + "_count" + "_auto"))
    {
      int pressid;
      for (Map.Entry<Integer, String> entry : resets.entrySet()) 
      {
        pressid = entry.getKey();
        String value = entry.getValue();
        //Log.i("KEY, VAL: ", Integer.toString(pressid) + " : " + value);
        if (value.equals(t.getText() + "_count" + "_auto"))
        {
          //Log.i("IN THE LOOP: ", Integer.toString(pressid));
          menu.add(0, pressid, 0, auto);        
          break;
        }
      }
    }
    else
    {
      menu.add(0, longPressId, 0, auto);        
      resets.put(longPressId,(String) t.getText() + "_count" + "_auto");
      longPressId++;
    }

    // and this to open the set alert activity
    String alert =  t.getText() + ": " + getString(R.string.sal);
    if (resets.containsValue(t.getText() + "_count" + "_alert"))
    {
      int pressid;
      for (Map.Entry<Integer, String> entry : resets.entrySet()) 
      {
        pressid = entry.getKey();
        String value = entry.getValue();
        //Log.i("KEY, VAL: ", Integer.toString(pressid) + " : " + value);
        if (value.equals(t.getText() + "_count" + "_alert"))
        {
          //Log.i("IN THE LOOP: ", Integer.toString(pressid));
          menu.add(0, pressid, 0, alert);        
          break;
        }
      }
    }
    else
    {
      menu.add(0, longPressId, 0, alert);        
      resets.put(longPressId,(String) t.getText() + "_count" + "_alert");
      longPressId++;
    }

  }

  @Override
  @TargetApi(11)
  @SuppressLint("UseSparseArrays")
  public boolean onContextItemSelected(MenuItem item) 
  {
    String pressed = resets.get(item.getItemId());
    final String[] clicked = resets.get(item.getItemId()).split("_");
    String lastOne = clicked[clicked.length-1];
    String tagName = pressed.replaceAll("_" + lastOne, "");


    /*
    Log.i("STUFF: ", pressed + " : " + lastOne + " : " + tagName);
    Log.i("PRESSED ", pressed);
    Log.i("OPTION SELECTED ", Integer.toString(item.getItemId()));
    Log.i("OPTIONS ", resets.toString());
    */

    if (lastOne.equals("reset"))
    {
      // reset this count to 0
      TextView toZero = (TextView) layout.findViewWithTag(tagName);
      int rt = reset_levels.get(clicked[0]);
      toZero.setText(String.valueOf(rt));
      currcount.put(clicked[0],String.valueOf(rt));
      return true;
    }
    else if (lastOne.equals("auto")) 
    { 
      // http://www.androidsnippets.com/prompt-user-input-with-an-alertdialog
      // set an auto-reset value for this count
      AlertDialog.Builder alert = new AlertDialog.Builder(this);

      alert.setTitle(getString(R.string.arTitle));
      if (android.os.Build.VERSION.SDK_INT < 11)
      {
        alert.setMessage(getString(R.string.arMsgShort));
      }
      else
      {
        alert.setMessage(getString(R.string.arMsg));
      }

      // Set an NumberPicker view to get user input
      final EditText input_gb = new EditText(this);;
      final NumberPicker input = new NumberPicker(this);
      if (android.os.Build.VERSION.SDK_INT < 11)
      {
        input_gb.setInputType(InputType.TYPE_CLASS_NUMBER);
        input_gb.setText(auto_resets.get(clicked[0]).toString());
        alert.setView(input_gb);
      }
      else
      {
        input.setMinValue(0);
        input.setMaxValue(spinMax);
        input.setValue(auto_resets.get(clicked[0]));

        EditText editText = findInput(input);
        TextWatcher tw = new TextWatcher()
        {
          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {}

          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          @Override
          public void afterTextChanged(Editable s)
          {
            if (s.toString().length() != 0) {
              Integer value = Integer.parseInt(s.toString());
              if (value >= input.getMinValue()) {
                input.setValue(value);
              }
            }
          }
        };
        editText.addTextChangedListener(tw);

        alert.setView(input);
      }

      alert.setPositiveButton(getString(R.string.alertOk), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          int value;
          if (android.os.Build.VERSION.SDK_INT < 11)
          {
            value = Integer.parseInt(input_gb.getText().toString());
          }
          else
          {
            value = input.getValue();
          }

          // Do something with value!
          //Log.i("PICKED VALUE: ", Integer.toString(value));
          auto_resets.put(clicked[0],value);
          saveData();
          drawScreen();
        }
      });

      alert.setNegativeButton(getString(R.string.alertCancel), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          // Canceled.
        }
      });

      alert.show();
      return true; 
    }
    else if (lastOne.equals("alert")) 
    { 
      // http://www.androidsnippets.com/prompt-user-input-with-an-alertdialog
      // set an alert for this count
      AlertDialog.Builder alert = new AlertDialog.Builder(this);
      alert.setTitle(getString(R.string.rowAlertTitle));
      if (android.os.Build.VERSION.SDK_INT < 11)
      {
        alert.setMessage(getString(R.string.rowAlertMsgShort));
      }
      else
      {
        alert.setMessage(getString(R.string.rowAlertMsg));
      }

      LinearLayout group = new LinearLayout(CountingActivity.this);
      group.setOrientation(LinearLayout.VERTICAL);
      group.setVerticalScrollBarEnabled(true);

      // Set an EditText view to get user input 
      final EditText inmsg = new EditText(this);
     
      // Set an NumberPicker view to get user input 
      final NumberPicker input = new NumberPicker(this);
      final EditText input_gb = new EditText(this);
      if (android.os.Build.VERSION.SDK_INT >= 11)
      {
        input.setMinValue(0); 
        input.setMaxValue(spinMax);
        EditText editText = findInput(input);
        TextWatcher tw = new TextWatcher()
        {
          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {}

          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          @Override
          public void afterTextChanged(Editable s)
          {
            if (s.toString().length() != 0) {
              Integer value = Integer.parseInt(s.toString());
              if (value >= input.getMinValue()) {
                input.setValue(value);
              }
            }
          }
        };
        editText.addTextChangedListener(tw);
      }

      // set the current values in the view
      /*
      List<Map<Integer,String>> tvals = alerts.get(clicked[0]);
      for (Map<Integer,String> uvals : tvals)
      {
        for (Map.Entry<Integer, String> subentry : uvals.entrySet())
        {
          if (android.os.Build.VERSION.SDK_INT < 11)
          {
            input_gb.setText(subentry.getKey().toString());
          }
          else
          {
            input.setValue(subentry.getKey());
          }
          inmsg.setText(subentry.getValue());
        }
      }
      */

      // now they should be added, having all the correct values and that
      group.addView(inmsg);
      if (android.os.Build.VERSION.SDK_INT < 11)
      {
        group.addView(input_gb);
      }
      else
      {
        group.addView(input);
      }

      alert.setPositiveButton(getString(R.string.alertOk), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          String msg = inmsg.getText().toString();
          int value;
          if (android.os.Build.VERSION.SDK_INT < 11)
          {
            value = Integer.parseInt(input_gb.getText().toString());
          }
          else
          {
            value = input.getValue();
          }
          // Do something with value!
          //Log.i("PICKED VALUE: ", Integer.toString(value) + " : " + msg);
          HashMap<Integer,String> newalert = new HashMap<Integer,String>();
          newalert.put(value,msg);
          if (alerts.containsKey(clicked[0]))
          {
            alerts.get(clicked[0]).add(newalert);
          }
          else
          {
            List list = new ArrayList<Map<Integer,String>>();
            list.add(newalert);
            alerts.put(clicked[0], list);
          }
          saveData();
          drawScreen();
        }
      });

      alert.setNegativeButton(getString(R.string.alertCancel), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          // Cancel!
        }
      });

      alert.setView(group);

      alert.show();
      return true; 
    }
    else if (lastOne.equals("level")) 
    { 
      // http://www.androidsnippets.com/prompt-user-input-with-an-alertdialog
      AlertDialog.Builder alert = new AlertDialog.Builder(this);

      alert.setTitle(getString(R.string.rlTitle));
      if (android.os.Build.VERSION.SDK_INT < 11)
      {
        alert.setMessage(getString(R.string.rlMsgShort));
      }
      else
      {
        alert.setMessage(getString(R.string.rlMsg));
      }

      // Set an NumberPicker view to get user input 
      final EditText input_gb = new EditText(this);
      final NumberPicker input = new NumberPicker(this);
      if (android.os.Build.VERSION.SDK_INT < 11)
      {
        input_gb.setInputType(InputType.TYPE_CLASS_NUMBER);
        input_gb.setText(reset_levels.get(clicked[0]).toString());
        alert.setView(input_gb);
      }
      else
      {
        input.setMinValue(0); 
        input.setMaxValue(spinMax);
        input.setValue(reset_levels.get(clicked[0]));
        EditText editText = findInput(input);
        TextWatcher tw = new TextWatcher()
        {
          @Override
          public void onTextChanged(CharSequence s, int start, int before, int count) {}

          @Override
          public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

          @Override
          public void afterTextChanged(Editable s)
          {
            if (s.toString().length() != 0) {
              Integer value = Integer.parseInt(s.toString());
              if (value >= input.getMinValue()) {
                input.setValue(value);
              }
            }
          }
        };
        editText.addTextChangedListener(tw);
        alert.setView(input);
      }

      alert.setPositiveButton(getString(R.string.alertOk), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          int value;
          if (android.os.Build.VERSION.SDK_INT < 11)
          {
            value = Integer.parseInt(input_gb.getText().toString());
          }
          else
          {
            value = input.getValue();
          }

          // Do something with value!
          //Log.i("PICKED VALUE: ", Integer.toString(value));
          reset_levels.put(clicked[0],value);
          saveData();
          drawScreen();
        }
      });

      alert.setNegativeButton(getString(R.string.alertCancel), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
          // Canceled.
        }
      });

      alert.show();
      return true; 
    }
    return true;
  }


  /*
    From: http://stackoverflow.com/questions/18944997/numberpicker-doesnt-work-with-keyboard
    To fix numberpicker keyboard bug
   */
  private EditText findInput(ViewGroup np)
  {
    int count = np.getChildCount();
    for (int i = 0; i < count; i++)
    {
      final View child = np.getChildAt(i);
      if (child instanceof ViewGroup)
      {
        findInput((ViewGroup) child);
      }
      else if (child instanceof EditText)
      {
        return (EditText) child;
      }
    }
    return null;
  }

}
